package com.ddh.ddhsanguogame.webSocket.handler;

import com.ddh.ddhsanguogame.constant.MessageTypeConstants;
import com.ddh.ddhsanguogame.entity.CardUser;
import com.ddh.ddhsanguogame.service.IUserService;
import com.ddh.ddhsanguogame.utils.SpringContextUtils;
import com.ddh.ddhsanguogame.webSocket.entity.CardMessageRequest;
import com.ddh.ddhsanguogame.webSocket.service.MessageService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;


@Component
@Slf4j
public class UserWebSocketHandler extends TextWebSocketHandler {

    private static final ObjectMapper objectMapper = new ObjectMapper(); // 创建 ObjectMapper 实例

    // 存储每个用户的连接，键为 userId，值为 WebSocketSession
    private static final ConcurrentHashMap<Long, WebSocketSession> userSessionMap = new ConcurrentHashMap<>();

    /**
     * 处理接收到的文本消息。
     *
     * @param session 与客户端的 WebSocket 会话
     * @param message 接收到的消息
     * @throws IOException 如果发送消息时发生 I/O 错误
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        String payload = message.getPayload();
        CardMessageRequest cardMessageRequest = objectMapper.readValue(payload, CardMessageRequest.class);
        Long userId = (Long) session.getAttributes().get("userId");
        cardMessageRequest.setSendTime(new Date());
        cardMessageRequest.setSenderId(userId);
        // 调用消息服务处理消息
        switch (cardMessageRequest.getMessageType()) {
            //广播，给所有人发消息(世界频道)
            case MessageTypeConstants.WORLD:
                MessageService messageServiceWorld = SpringContextUtils.getBean(MessageService.class);
                messageServiceWorld.saveMessage(objectMapper.writeValueAsString(cardMessageRequest));
                broadcastMessage(cardMessageRequest.getContent());
                break;
            // 私聊
            case MessageTypeConstants.PRIVATE:
                MessageService messageServicePrivate = SpringContextUtils.getBean(MessageService.class);
                messageServicePrivate.savePrivateMessage(objectMapper.writeValueAsString(cardMessageRequest));
                sendPrivateMessage(cardMessageRequest.getReceiverId(), cardMessageRequest.getContent());
                break;
            // 同盟频道
            case MessageTypeConstants.ALLIANCE:
                break;
            // 系统频道
            case MessageTypeConstants.SYSTEM:
                break;
            default:
        }
    }

    /**
     * 在 WebSocket 连接建立成功后调用。
     *
     * @param session 与客户端的 WebSocket 会话
     * @throws Exception 如果发生任何异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Long userId = (Long) session.getAttributes().get("userId");
        if (userId != null) {
            userSessionMap.put(userId, session);
            IUserService userService = SpringContextUtils.getBean(IUserService.class);
            CardUser cardUser = userService.getUserById(userId);
            broadcastMessage("用户:" + cardUser.getNickname() + "进入游戏");
        }
    }

    /**
     * 在 WebSocket 连接关闭后调用。
     *
     * @param session 与客户端的 WebSocket 会话
     * @param status  连接关闭的状态
     * @throws Exception 如果发生任何异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 移除该用户的连接
        userSessionMap.values().remove(session);
    }


    /**
     * 向所有连接的用户广播消息
     *
     * @param message 要广播的消息内容
     */
    public void broadcastMessage(String message) {
        userSessionMap.values().forEach(session -> {
            // 检查会话是否打开
            if (session.isOpen()) {
                try {
                    session.sendMessage(new TextMessage(message));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }


    /**
     * 向指定用户发送私聊消息。
     *
     * @param toUserId 目标用户 ID
     * @param message  消息内容
     */
    public void sendPrivateMessage(Long toUserId, String message) {
        WebSocketSession session = userSessionMap.get(toUserId);
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 从 WebSocket 会话中获取用户 ID
     * @param session WebSocket 会话
     * @return 用户 ID
     */
    private String getUserIdFromSession(WebSocketSession session) {
        return (String) session.getAttributes().get("userId");
    }
}
